﻿using IWshRuntimeLibrary;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Shapes;
using static System.Net.WebRequestMethods;

namespace WpfApp1
{
    public static class TryGetExeLargeIcon
    {
        //指定存放图标的文件夹
        public static string folderToSave = MainWindow.folderToSave + @"imgs\";

        public static string fileName { get; private set; }
        public static string ExefilePath { get; private set; }


        /// <summary>
        /// 获取.lnk文件的目标位置
        /// </summary>
        /// <param name="lnkPath"></param>
        /// <returns></returns>
        public static string GetLnkTarget(string lnkPath)
        {
            if (!System.IO.File.Exists(lnkPath)) return "";
        
            WshShell shell = new WshShell();
            IWshShortcut link = (IWshShortcut)shell.CreateShortcut(lnkPath);

            return link.TargetPath.ToString();
        }

        /// <summary>
        /// 获取exe文件的大图片并保存 folderToSave设置的文件目录下面
        /// </summary>
        /// <param name="file">可以是.exe/.lnk的文件绝对地址</param>
        [STAThread]
        public static void TryGetExeLargeIconGo(string file)
        {
            string strLastName=file.Substring(file.LastIndexOf(".") + 1, (file.Length - file.LastIndexOf(".") - 1)); //根据输入的地址确定下载的文件后缀名
            if(strLastName== "lnk")
            {
                file=GetLnkTarget(file);
            }

            ExefilePath = file;

            if (!Directory.Exists(folderToSave)) Directory.CreateDirectory(folderToSave);

            //选中文件中的图标总数
            var iconTotalCount = PrivateExtractIcons(file, 0, 0, 0, null, null, 0, 0);

            //用于接收获取到的图标指针
            IntPtr[] hIcons = new IntPtr[iconTotalCount];
            //对应的图标id
            int[] ids = new int[iconTotalCount];
            //成功获取到的图标个数
            var successCount = PrivateExtractIcons(file, 0, 256, 256, hIcons, ids, iconTotalCount, 0);

            fileName = System.IO.Path.GetFileNameWithoutExtension(file).ToString();

            if (hIcons.Length<=0) return;

            try
            {
                var ico = System.Drawing.Icon.FromHandle(hIcons[0]);
                var myIcon = ico.ToBitmap();
                string ImgfilePath = folderToSave + fileName + ".png";
                myIcon.Save(ImgfilePath, ImageFormat.Png);
                DestroyIcon(hIcons[0]);
            }
            catch
            {
                return;
            }
          
            //遍历并保存图标
            //for (var i = 0; i<successCount; i++)
            // {
            //     //指针为空，跳过
            //     if (hIcons[i] == IntPtr.Zero) continue;
 
            //     using (var ico = System.Drawing.Icon.FromHandle(hIcons[i]))
            //     {
            //         using (var myIcon = ico.ToBitmap())
            //         {
            //             myIcon.Save(folderToSave + ids[i].ToString("000") + ".png", ImageFormat.Png);
            //         }
            //     }
            //     //内存回收
            //     DestroyIcon(hIcons[i]);
            // }
         }


         //details: https://msdn.microsoft.com/en-us/library/windows/desktop/ms648075(v=vs.85).aspx
         //Creates an array of handles to icons that are extracted from a specified file.
         //This function extracts from executable (.exe), DLL (.dll), icon (.ico), cursor (.cur), animated cursor (.ani), and bitmap (.bmp) files. 
         //Extractions from Windows 3.x 16-bit executables (.exe or .dll) are also supported.
         [DllImport("User32.dll")]
         public static extern int PrivateExtractIcons(
             string lpszFile, //file name
             int nIconIndex,  //The zero-based index of the first icon to extract.
             int cxIcon,      //The horizontal icon size wanted.
             int cyIcon,      //The vertical icon size wanted.
             IntPtr[] phicon, //(out) A pointer to the returned array of icon handles.
             int[] piconid,   //(out) A pointer to a returned resource identifier.
             int nIcons,      //The number of icons to extract from the file. Only valid when *.exe and *.dll
             int flags        //Specifies flags that control this function.
         );

         //details:https://msdn.microsoft.com/en-us/library/windows/desktop/ms648063(v=vs.85).aspx
         //Destroys an icon and frees any memory the icon occupied.
         [DllImport("User32.dll")]
         public static extern bool DestroyIcon(
             IntPtr hIcon //A handle to the icon to be destroyed. The icon must not be in use.
         );


       
    }
}
